package com.flute.framework.autoprompt;

import java.util.ArrayList;
import java.util.List;

public class WordResult {
	private Token[][] tokens;
	private int length = 10;
	private WordCategory cate;

	public WordResult(WordCategory cat) {
		if(cat == null){
			throw new NullPointerException("WordCategory is null");
		}
		this.tokens = new Token[cat.getCount()][1];
		this.cate = cat;
		if (cate.getResultSize() > 0) {
			this.length = cate.getResultSize();
		}
	}

	public void addToken(Token token, String key) {
		if (!containsText(token.getOriginalText(), key)) {
			insertToList(token, key);

			List<Token> tokens = arrayToList(key);

			if (tokens.size() >= length) {
				tokens.remove(tokens.size() - 1);
			}

			listToArray(tokens, key);
		}
	}

	public void deleteToken(String originalText, String key) {
		List<Token> tokens = arrayToList(key);
		for (int i = 0; i < tokens.size(); i++) {
			if (tokens.get(i).getOriginalText().equals(originalText)) {
				tokens.remove(i);
				break;
			}
		}
		listToArray(tokens, key);
	}

	private void listToArray(List<Token> list, String key) {
		// if (list.size() != tokens[cate.getCategoryKey(key)].length) {
		tokens[cate.getCategoryKey(key)] = new Token[list.size()];
		// }
		for (int i = 0; i < Math.min(list.size(), length); i++) {
			tokens[cate.getCategoryKey(key)][i] = list.get(i);
		}
	}

	private List<Token> arrayToList(String key) {
		List<Token> list = new ArrayList<Token>();
		for (int i = 0; i < tokens[cate.getCategoryKey(key)].length; i++) {
			if (tokens[cate.getCategoryKey(key)][i] != null) {
				list.add(tokens[cate.getCategoryKey(key)][i]);
			}
		}

		return list;
	}

	public void insertToList(Token token, String key) {
		List<Token> tokens = arrayToList(key);
		int start = 0;
		int end = tokens.size();
		if (tokens.size() == 0) {
			tokens.add(token);
		} else {
			if (token.getPriority().higherThan(tokens.get(start).getPriority())) {
				tokens.add(start, token);
			} else if (tokens.get(end - 1).getPriority().higherThan(
					token.getPriority())) {
				tokens.add(token);
			} else {
				while (true) {
					if (end <= start) {
						tokens.add(start, token);
						break;
					} else {
						int middle = (start + end) / 2;
						if (tokens.get(middle).getPriority().higherThan(
								token.getPriority())) {
							if (start == middle) {
								tokens.add(end, token);
								break;
							} else {
								start = middle;
							}
						} else if (token.getPriority().higherThan(
								tokens.get(middle).getPriority())) {
							if (end == middle) {
								tokens.add(start, token);
								break;
							} else {
								end = middle;
							}
						}
					}
				}
			}
		}

		listToArray(tokens, key);
	}

	public List<Token> getTokens(String key) {
		return arrayToList(key);
	}

	public boolean containsText(String text, String key) {
		if (tokens[cate.getCategoryKey(key)] != null) {
			for (Token tk : tokens[cate.getCategoryKey(key)]) {
				if (tk != null) {
					if (tk.getOriginalText().trim().equals(text.trim())) {
						return true;
					}
				}
			}
		}

		return false;
	}

	public String toString() {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < tokens.length; i++) {
			if (tokens[i] != null) {
				sb.append(cate.getCategoryName(i) + ":");
				for (int j = 0; j < tokens[i].length; j++) {
					sb.append(tokens[i][j].getOriginalText() + ":"
							+ tokens[i][j].getPriority().getPriorityString()
							+ "\n");
				}
			}
		}

		return sb.toString().trim();
	}

}
